<?php
	namespace ampleharvest\task\process_data;

	use\ampleharvest\code;

	require_once dirname(dirname(dirname(dirname(__FILE__)))) . "/config/cConfig.php";
	require_once dirname(dirname(dirname(dirname(__FILE__)))) . "/abstract_classes/abs_Task.php";
	require_once dirname(dirname(dirname(dirname(__FILE__)))) . "/classes/Tables/cTABLE_Data.php";
	require_once dirname(dirname(dirname(dirname(__FILE__)))) . "/classes/cThread.php";
	require_once dirname(dirname(dirname(dirname(__FILE__)))) . '/validation/json/cJsonValidator.php';

	$arr_Params = array("date::");

	$arr_Options = getopt("c::", $arr_Params);
	/**
	 * @brief This Task Handles the Processing of the given json object into database table format
	 *
	 * - Revision History
	 *  - 0.1
	 * 	 - <b>Date</b>: 02 JUN 2011
	 * 	 - <b>Author</b>: Randy Blancett
	 * 	  - Initial Version
	 *  - 0.2
	 * 	 - <b>Date</b>: 12 SEP 2011
	 * 	 - <b>Author</b>: Randy Blancett
	 * 	  - Converted original script into a task
	 * 	  - Added Threading capabilities
	 *
	 * @author Randy Blancett
	 * @version 0.2
	 * @ingroup code
																	
	 */
	class process_Data_1 extends \abs_Task
	{
		const C_STR_NAME = "process_Data_1";
		const C_INT_THREADS = 2;
		
		protected $m_obj_StartDate = null;
		protected $m_arr_Threads = null;
		protected $arr_Options = null;

		public function __construct($str_LockPath,$arr_Options = array())
		{
			$this->m_obj_StartDate = new \DateTime();
			$this->set_LockPath($str_LockPath);
			$this->set_Name(self::C_STR_NAME);
			$this->m_arr_Threads = array();
			$this->arr_Options = $arr_Options;
			parent::__construct();
		}

		public function run($bool_Force = false)
		{
			//print("Test".__LINE__."\n");
			$this->set_Force($bool_Force);
			if (!parent::run())
			{
				return false;
			}

			for ($int_I = 0; $int_I < self::C_INT_THREADS; $int_I++)
			{
				$this->startThread();
			}

			$this->wait4Threads();

			return true;
		}

		private function startThread()
		{
			$str_Command = __FILE__ . " -c --date=\"".$this->m_obj_StartDate->format("c")."\"";
			print($str_Command . "\n");
			$int_I = sizeof($this->m_arr_Threads);

			$this->m_arr_Threads[$int_I] = \cThread::Create($str_Command, code\cConfig::C_STR_PATH_PHP);
			$obj_Thread = $this->m_arr_Threads[$int_I];
			$str_Return = $obj_Thread->listen(false);
			print($str_Return);
			if (!$obj_Thread->isActive())
			{
				$obj_Thread->close();
				unset($this->m_arr_Threads[$int_I]);
				return;
			}
			if ($str_Return == "No Items to process")
			{
				print("was no return");
			}
		}

		private function wait4Threads()
		{
			while (sizeof($this->m_arr_Threads) > 0)
			{ //No Items to process
				foreach ($this->m_arr_Threads as $str_Key => $obj_Thread)
				{
					if (!$obj_Thread->isActive())
					{
						$str_Return = $obj_Thread->listen();
						print($str_Return);
						$obj_Thread->close();
						unset($this->m_arr_Threads[$str_Key]);
						if (strstr($str_Return, "No Items to process"))
						{
							print("was no return" . PHP_EOL);
						}
						else 
						{
						$this->startThread();
						}
					}
				}
			}
		}

		public function runChunk()
		{
			/*			
			 set_error_handler('exceptions_error_handler');
												
			 function exceptions_error_handler($severity, $message, $filename, $lineno)
			 {
			 if (error_reporting() == 0)
			 {
			 return;
			 }
			 if (error_reporting() & $severity)
			 {
			 throw new ErrorException($message, 0, $severity, $filename, $lineno);
			 }
			 }
			 */

			$this->m_obj_StartDate = new \DateTime($this->arr_Options["date"]);
			
			//Number of Data sets to process in one pass.
			$int_GroupSize = 100;

			$arr_DataSets = array();

			$obj_TABLE_Data = new \cTABLE_Data();
			

			//Search for all Rows that have a current status of New
			$obj_TABLE_Data->start_Group();

			$obj_TABLE_Data->add_ColumnQuery($obj_TABLE_Data->m_int_COL_Status, \cTABLE_Data::C_INT_STATUS_NEW);
			$obj_TABLE_Data->add_ColumnQuery($obj_TABLE_Data->m_int_COL_HarvestDate, $this->m_obj_StartDate->format("Y:m:d H:i:s"),\cCondition::c_str_OPERATOR_LESS);

			$obj_TABLE_Data->end_Group();
			//Search for all Rows that have a diffrent datatoken form the process token (this means the Json object has changed)
/*			
			$obj_TABLE_Data->start_Group(\cQuery::c_str_JOIN_OR);

			$obj_TABLE_Data->add_ColumnQuery($obj_TABLE_Data->m_int_COL_DataToken,
				$obj_TABLE_Data->get_Column_Name($obj_TABLE_Data->m_int_COL_ProcessToken),
				\cCondition::c_str_OPERATOR_NOT,
				\cQuery::c_str_JOIN_AND,
				\cCondition::C_INT_FORMAT_COLUMN);
				
			$obj_TABLE_Data->add_ColumnQuery($obj_TABLE_Data->m_int_COL_HarvestDate, $this->m_obj_StartDate->format("Y:m:d H:i:s"),\cCondition::c_str_OPERATOR_LESS);

			$obj_TABLE_Data->add_ColumnQuery($obj_TABLE_Data->m_int_COL_Status,
				\cTABLE_Data::C_INT_STATUS_PROCESSING_DATA,
				\cCondition::c_str_OPERATOR_GREATER);

			$obj_TABLE_Data->end_Group();
*/
			$obj_TABLE_Data->set_Limit($int_GroupSize);

			//Do Query
			$int_Items = $obj_TABLE_Data->do_Search();
			$this->log("Processing " . $int_Items . " rows of data.");

			if ($int_Items < 1)
			{
				print("No Items to process\n" . PHP_EOL);
				
				return "kill it";
			}

			$arr_Results = $obj_TABLE_Data->get_ResultSet();

			//print_r($arr_DataSets);
			foreach ($arr_Results as $arr_Result)
			{
				$obj_TABLE_Data->clear();
				$obj_TABLE_Data->load_DataFromArray($arr_Result);
				$arr_DataSets[] = $arr_Result;

				$obj_TABLE_Data->set_data();

				$obj_TABLE_Data->set_status(\cTABLE_Data::C_INT_STATUS_PROCESSING_DATA);

				$obj_TABLE_Data->save_Data2DB();
			}

			print("All items moved to Processing Data status." . PHP_EOL);

			foreach ($arr_DataSets as $arr_DataSet)
			{
				$obj_TABLE_Data->clear();
				$obj_TABLE_Data->load_DataFromArray($arr_DataSet);

				$bool_Save = true;

				$str_Json = \cTABLE_Data::decode($obj_TABLE_Data->get_data());

				try
				{
					$arr_Json = json_decode($str_Json);
				}
				catch (Exception $e)
				{
					$obj_TABLE_Data->set_status(\cTABLE_Data::C_INT_STATUS_STAGE_1_FAIL);

					if (!$obj_TABLE_Data->save_Data2DB())
					{
						$this->log_Error($obj_TABLE_Data->get_id() . " had an error updateing its information in the database.");
						print("Error Writeing to Database\n");
					}

					$this->log_Error($obj_TABLE_Data->get_id() . " the following problem unserializeing " . $e);

					continue;
				}

				if ($this->validate_Json($arr_Json, $obj_TABLE_Data->get_id()))
				{
					if ($this->validate_Row($obj_TABLE_Data, $arr_Json))
					{
						if (isset($arr_Json->harvestDate))
						{
							$obj_TABLE_Data->set_harvest_date($arr_Json->harvestDate);
						}
						if (isset($arr_Json->publishDate))
						{
							try
							{
								$obj_TABLE_Data->set_publish_date($arr_Json->publishDate);
							}
							catch (Exception $e)
							{

							}
						}
						if (isset($arr_Json->origId))
						{
							$obj_TABLE_Data->set_orig_id($arr_Json->origId);
						}
						if (isset($arr_Json->page))
						{
							$obj_TABLE_Data->set_page($arr_Json->page);
						}
						if (isset($arr_Json->source))
						{
							$obj_TABLE_Data->set_source($arr_Json->source);
						}
						if (isset($arr_Json->category))
						{
							$obj_TABLE_Data->set_category($arr_Json->category);
						}

						$obj_TABLE_Data->set_processToken($obj_TABLE_Data->get_dataToken());
						$obj_TABLE_Data->set_status(\cTABLE_Data::C_INT_STATUS_STAGE_1_SUCCESS);
					}
					else
					{
						$obj_TABLE_Data->set_status(\cTABLE_Data::C_INT_STATUS_STAGE_1_FAIL);
					}
				}
				else
				{
					$obj_TABLE_Data->set_status(\cTABLE_Data::C_INT_STATUS_STAGE_1_FAIL);
				}

				//		}
				if (!$obj_TABLE_Data->save_Data2DB())
				{
					$this->log_Error($obj_TABLE_Data->get_id() . " had an error updateing its information in the database.");
					print("Error Writeing to Database\n");
				}
				//print_r($arr_Json);
			}
		}

		private function validate_Json($obj_Json, $str_ID = "unknown")
		{
			$str_SchemaLoc = dirname(dirname(dirname(dirname(__FILE__)))) . "/validation/json/";
			$str_Schema = file_get_contents($str_SchemaLoc . "AmpleHarvest.json");
			\cJsonValidator::add_Path($str_SchemaLoc);

			$int_Return = \cJsonValidator::validate($obj_Json, $str_Schema);
			if ($int_Return < 0)
			{
				/*			
				 print($obj_TABLE_Data->get_id() . " had the following error parsing the json " . \cJsonValidator::convert_ErrorCode($int_Return) .
				 "\n Schema Location - " . \cJsonValidator::get_LastSchemaPos() .
				 "\n Json Location - " . \cJsonValidator::get_LastJsonPos() .
				 "\n Error Text - " . \cJsonValidator::get_ErrorText());
				 */

				$this->log_Error($str_ID . " had the following error parsing the json " . \cJsonValidator::convert_ErrorCode($int_Return) .
					"\n Schema Location - " . \cJsonValidator::get_LastSchemaPos() .
					"\n Json Location - " . \cJsonValidator::get_LastJsonPos() .
					"\n Error Text - " . \cJsonValidator::get_ErrorText());

				return false;
			}
			return true;
		}

		private function validate_Row(\cTABLE_Data $obj_Data, $obj_Json)
		{
			if ($obj_Data->get_id() != $obj_Json->id)
			{
				$this->log_Error($obj_Data->get_id() . " has miss matching IDs the row id and the Json ID must match");
				return false;
			}
			return true;
		}
	}

	if (isset($arr_Options["c"]))
	{
		$obj_Task = new process_Data_1(null,$arr_Options);
		$obj_Task->runChunk();

	}

?>